package com.licheedev.multifunctionview

import android.content.Context
import android.graphics.Color
import android.text.InputFilter
import android.text.InputType
import android.text.TextUtils
import android.text.method.DigitsKeyListener
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.*
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.core.view.isVisible


class MultiFunctionView @JvmOverloads constructor(
    private val mContext: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayoutCompat(mContext, attrs, defStyleAttr) {

    init {

        orientation = HORIZONTAL
        gravity = Gravity.CENTER_VERTICAL

        LayoutInflater.from(mContext).inflate(R.layout.view_multi_function, this, true)


    }

    val tvLeftLabel = findViewById<TextView>(R.id.leftLabel)
    val tvRightLabel = findViewById<TextView>(R.id.rightLabel)
    private val editBg = findViewById<MfvCheckableLinearLayout>(R.id.editBg)
    val editText = findViewById<AutoCompleteTextView>(R.id.editText)
    private val arrow = findViewById<ImageView>(R.id.drawDownArrow)
    val button1 = findViewById<Button>(R.id.button1)
    val button2 = findViewById<Button>(R.id.button2)

    private val adapter: ArrayAdapter<String>

    init {

        var allTextSize = 12f.dp2px()
        var widgetMargin = 4f.dp2px()


        var dimen: Int
        var color: Int
        var str: String?
        var drawable: Int?

        var itemLayout = R.layout.default_func_spinner_selection_item
        var itemTextId = 0

        if (attrs != null) {
            val typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.MultiFunctionView)

            allTextSize = typedArray.getDimensionPixelSize(
                R.styleable.MultiFunctionView_allTextSize,
                allTextSize
            )

            widgetMargin = typedArray.getDimensionPixelSize(
                R.styleable.MultiFunctionView_widgetMargin,
                widgetMargin
            )

            // 左边的文本
            tvLeftLabel.run {
                str = typedArray.getString(R.styleable.MultiFunctionView_leftLabelText)
                if (str.isNotNullOrEmpty()) {
                    text = str
                    visibility = View.VISIBLE
                } else {
                    visibility = View.GONE
                }

                color =
                    typedArray.getColor(R.styleable.MultiFunctionView_leftLabelColor, labelColor)
                setTextColor(color)

                dimen = typedArray.getDimensionPixelSize(
                    R.styleable.MultiFunctionView_leftLabelTextSize,
                    allTextSize
                )
                setTextPx(dimen)

                dimen = typedArray.getDimensionPixelSize(
                    R.styleable.MultiFunctionView_leftLabelWidth, 0
                )
                if (dimen > 0) {
                    setLayoutWidth(dimen)
                }

                val marqueeLimit =
                    typedArray.getInt(R.styleable.MultiFunctionView_leftMarqueeRepeatLimit, 3)
                setMarqueeRepeatLimit(marqueeLimit)
            }

            // 右边的文本
            tvRightLabel.run {
                str = typedArray.getString(R.styleable.MultiFunctionView_rightLabelText)
                if (str.isNotNullOrEmpty()) {
                    text = str
                    visibility = View.VISIBLE
                } else {
                    visibility = View.GONE
                }

                color =
                    typedArray.getColor(R.styleable.MultiFunctionView_rightLabelColor, labelColor)
                setTextColor(color)

                dimen = typedArray.getDimensionPixelSize(
                    R.styleable.MultiFunctionView_rightLabelTextSize,
                    allTextSize
                )
                setTextPx(dimen)
            }

            // 后面那两个按钮
            str = typedArray.getString(R.styleable.MultiFunctionView_button1Text)
            if (str.isNotNullOrEmpty()) {
                button1.text = str
                button1.setVisibility(View.VISIBLE)
            } else {
                button1.setVisibility(View.GONE)
            }
            str = typedArray.getString(R.styleable.MultiFunctionView_button2Text)
            if (str.isNotNullOrEmpty()) {
                button2.setText(str)
                button2.visibility = View.VISIBLE
            } else {
                button2.visibility = View.GONE
            }

            color =
                typedArray.getColor(R.styleable.MultiFunctionView_buttonTextColor, buttonTextColor)
            button1.setTextColor(color)
            button2.setTextColor(color)

            dimen = typedArray.getDimensionPixelSize(
                R.styleable.MultiFunctionView_buttonTextSize,
                allTextSize
            )
            button1.setTextPx(dimen)
            button2.setTextPx(dimen)

            drawable = typedArray.getResourceId(R.styleable.MultiFunctionView_buttonBg, 0)
            if (drawable != 0) {
                button1.setBackgroundResource(drawable)
                button2.setBackgroundResource(drawable)
            }

            val showButton = typedArray.getInt(R.styleable.MultiFunctionView_showButton, -1)
            if (showButton >= 0) {
                button1.visibility =
                    if (showButton == 1 || showButton == 3) View.VISIBLE else View.GONE
                button2.visibility =
                    if (showButton == 2 || showButton == 3) View.VISIBLE else View.GONE
            }

            // 中间的编辑/选择框

            color =
                typedArray.getColor(R.styleable.MultiFunctionView_editHintColor, hintColor)
            editText.setHintTextColor(color)
            str = typedArray.getString(R.styleable.MultiFunctionView_editHintText)
            if (str.isNotNullOrEmpty()) {
                editText.hint = str
            }

            color =
                typedArray.getColor(R.styleable.MultiFunctionView_editValueColor, labelColor)
            editText.setTextColor(color)
            str = typedArray.getString(R.styleable.MultiFunctionView_editValueText)
            if (str.isNotNullOrEmpty()) {
                editText.setText(str, false)
            }

            dimen = typedArray.getDimensionPixelSize(
                R.styleable.MultiFunctionView_editSelectionTextSize,
                allTextSize
            )
            editText.setTextPx(dimen)

            dimen = typedArray.getDimensionPixelSize(
                R.styleable.MultiFunctionView_editSelectionWidth,
                100f.dp2px()
            )
            editBg.setLayoutWidth(dimen)

            dimen = typedArray.getDimensionPixelSize(
                R.styleable.MultiFunctionView_editSelectionHeight,
                24f.dp2px()
            )
            editBg.setLayoutHeight(dimen)

            drawable =
                typedArray.getResourceId(R.styleable.MultiFunctionView_selectionArrowImage, 0)
            if (drawable != 0) {
                arrow.setImageResource(drawable)
            }

            val editMaxLen =
                typedArray.getInteger(R.styleable.MultiFunctionView_editTextMaxLength, 0)
            if (editMaxLen > 0) {
                editText.filters = arrayOf<InputFilter>(InputFilter.LengthFilter(editMaxLen))
            }

            val inputMode = typedArray.getInt(R.styleable.MultiFunctionView_editInputMode, 1)
            when (inputMode) {
                1 -> {
                    editText.setInputType(InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL)
                }

                2 -> {
                    editText.setInputType(InputType.TYPE_CLASS_TEXT)
                }

                3 -> {
                    editText.keyListener =
                        DigitsKeyListener.getInstance("0123456789-")
                }
            }

            val isEditText = typedArray.getBoolean(R.styleable.MultiFunctionView_isEditText, true)
            if (isEditText) {
                editText.isFocusable = true
                arrow.visibility = View.GONE
                drawable =
                    typedArray.getResourceId(
                        R.styleable.MultiFunctionView_ifEditBg,
                        R.drawable.func_selector_edit_value_bg
                    )
                editBg.setBackgroundResource(drawable)
            } else {
                editText.setFocusable(false);
                editText.setFocusableInTouchMode(false);
                editText.setOnClickListener {
                    editBg.performClick() // 转去调用背景的点击事件
                }

                arrow.visibility = View.VISIBLE
                drawable =
                    typedArray.getResourceId(
                        R.styleable.MultiFunctionView_ifSelectionBg,
                        R.drawable.func_selector_select_value_bg
                    )
                editBg.setBackgroundResource(drawable)
            }

            val showArrow =
                typedArray.getBoolean(R.styleable.MultiFunctionView_showSelectionArrow, !isEditText)
            arrow.visibility = if (showArrow) View.VISIBLE else View.GONE


            val showEdit =
                typedArray.getBoolean(R.styleable.MultiFunctionView_showEditSelection, true)

            if (!showEdit) {
                editBg.visibility = View.GONE
                editText.visibility = View.GONE
                arrow.visibility = View.GONE
            }

            itemLayout = typedArray.getResourceId(
                R.styleable.MultiFunctionView_spinnerItemLayout,
                itemLayout
            )
            itemTextId =
                typedArray.getResourceId(R.styleable.MultiFunctionView_spinnerItemTextId, 0)

            typedArray.recycle()
        }

        editText.setOnDismissListener {
            updateDrawDown(false)
        }
        editText.onItemClickListener = object : AdapterView.OnItemClickListener {
            override fun onItemClick(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                changeSelectedIndex(position)
            }
        }


        editBg.setOnClickListener {

            if (!arrow.isVisible) {
                return@setOnClickListener
            }
            editBg.toggle()
            updateDrawDown(editBg.isChecked)

        }

        //arrow.setOnCheckedChangeListener { buttonView, isChecked ->
        //    if (buttonView.isPressed) {
        //        if (values != null) if (isChecked) editText.showDropDown() else editText.dismissDropDown()
        //    }
        //    editBg.isSelected = isChecked
        //}


        //tvLeftLabel.setMargin(widgetMargin)
        tvRightLabel.setMargin(widgetMargin)
        editBg.setMargin(widgetMargin)
        button1.setMargin(widgetMargin)
        button2.setMargin(widgetMargin)
        //arrow.setMargin(0, widgetMargin)
        //editText.setMargin(widgetMargin, 0)
        //editText.setGoneMargin(0, widgetMargin)

        adapter = ArrayAdapter<String>(mContext, itemLayout, itemTextId)
        editText.setAdapter(adapter)
    }

    private fun changeSelectedIndex(index: Int) {
        val oldIndex = selectedIndex
        selectedIndex = index
        if (oldIndex != index) {
            onChangeSelectedListener?.onChangeSelected(this, index, oldIndex)
        }
    }


    /** 更新下拉状态 */
    private fun updateDrawDown(isChecked: Boolean) {
        if (isChecked) {
            if (!editText.isPopupShowing) {
                editText.showDropDown()
            }
        } else {
            if (editText.isPopupShowing) {
                editText.dismissDropDown()
            }
        }
        editBg.isChecked = isChecked
    }


    private var keys: List<String>? = null
    private var values: List<String>? = null
    private var selectedIndex = -1

    fun setData(keys: List<String>, values: List<String>) {
        this.keys = keys
        this.values = values
        adapter.clear()
        adapter.addAll(keys)
        editText.setText(keys[0], false)
        changeSelectedIndex(0)
    }

    fun setData(keys: List<String>) {
        setData(keys, keys)
    }

    fun setData(map: Map<String, *>) {
        val keys = mutableListOf<String>()
        val values = mutableListOf<String>()

        map.forEach() {
            keys.add(it.key)
            values.add(it.value.toString())
        }
        setData(keys, values)
    }

    var currentText: String
        get() {
            return editText.text.toString().trim()
        }
        set(value) {
            editText.setText(value, false)
        }

    val currentValue: String
        get() {
            val values_ = values
            val selectedIndex_ = selectedIndex
            if (values_.isNullOrEmpty() || selectedIndex_ < 0) {
                return currentText
            }
            return values_.get(selectedIndex_)
        }

    val currentInt: Int?
        get() {
            return currentValue.toIntOrNull()
        }

    val currentIntOrZero: Int get() = currentInt ?: 0

    fun selectByValue(value: Any) {
        val index = values?.indexOf(value.toString()) ?: -1
        if (index >= 0) {
            changeSelectedIndex(index)
            editText.setText(keys?.get(selectedIndex), false)
        } else {
            changeSelectedIndex(-1)
            editText.setText("", false)
        }
    }

    val isEmpty: Boolean
        get() = editText.text.toString().isEmpty()


    private fun View.setLayoutWidth(dimen: Int) {
        this.layoutParams.width = dimen
    }

    private fun View.setLayoutHeight(dimen: Int) {
        this.layoutParams.height = dimen
    }

    private fun View.setMargin(left: Int = 0, right: Int = 0) {
        (this.layoutParams as LinearLayoutCompat.LayoutParams).leftMargin = left
        (this.layoutParams as LinearLayoutCompat.LayoutParams).rightMargin = right
    }

    //private fun View.setGoneMargin(left: Int = 0, right: Int = 0) {
    //    (this.layoutParams as ConstraintLayout.LayoutParams).goneLeftMargin = left
    //    (this.layoutParams as ConstraintLayout.LayoutParams).goneRightMargin = right
    //}

    private fun TextView.setTextPx(px: Int) {
        this.setTextSize(TypedValue.COMPLEX_UNIT_PX, px.toFloat())
    }

    private fun Float.dp2px(): Int {
        val density = resources.displayMetrics.density
        return (this * density + 0.5).toInt()
    }

    private fun CharSequence?.isNotNullOrEmpty(): Boolean {
        return !TextUtils.isEmpty(this)
    }

    companion object {
        private val labelColor = Color.parseColor("#333333")
        private val buttonTextColor = Color.WHITE
        private val hintColor = Color.parseColor("#999999")
    }

    var onChangeSelectedListener: OnChangeSelectedListener? = null

    interface OnChangeSelectedListener {
        fun onChangeSelected(view: MultiFunctionView, index: Int, oldIndex: Int)
    }

}